#ifndef NET_SOCKET_OPTION_H_
#define NET_SOCKET_OPTION_H_
#include <fermat/net/socket_address.h>
#include <fermat/common/timespan.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cassert>
#include <cerrno>
#include <cstring>
#include <string>
#include <utility>

struct tcp_info;
namespace fermat {
namespace net {

class SocketOption {
public:
    /*!
     * [setNonBlock description]
     * @author lothar<liyinbin> 2017-04-01
     * @param  fd [description]
     * @param  on [description]
     * @return    [description]
     */
    static bool setNonBlock(int fd, bool on);

    /*!
    * @return the current local socket address.
    */
    static SocketAddress getLocalAddress(int fd);

    /*!
    * @return the current peer socket address.
    */
    static SocketAddress getPeerAddress(int fd);

    /*!
     * @return true iff sucess shutdown the given 
     * fd read/ write/ or all read and write.
     * some time you need to shutdown fd before you 
     * close it. for time wait status.
     */
    static bool shutdownRead(int fd);
    static bool shutdownWrite(int fd);
    static bool shutdownAll(int fd);

    /*!
    * @return true iff sucess close the given 
    * fd. 
    */
    static bool close(int fd);

    static bool getsockopt(int fd, int level, int optname,
                   void* optval, socklen_t* optlen);

    static bool setsockopt(int fd, int level, int optname,
                   const void* optval, socklen_t optlen);

    /*!
    * Enable sending of keep-alive messages on connection-oriented sockets.
    */
    static  bool setKeepAlive(int fd, bool activate = true);

    /*!
    * Enable SO_REUSEADDR, which allows the socket to be bound more quickly to
    * previously used ports.
    */
    static bool setReuseAddr(int fd, bool activate = true);
    static bool setReusePort(int fd, bool activate = true);

    static bool setSoLinger(int fd, bool doLinger, int seconds);

    static bool setTcpQuickAck(int fd, bool quickAck);

    static bool setTimeOption(int fd, int option, int milliseconds);

    /*!
    * If set, disable the Nagle algorithm. This means that segments are always
    * sent as soon as possible, even if there is only a small amount of data.
    */
    static bool setNoDelay(int fd, bool activate = true);

    /*!
    * Set SO_SNDBUF socket option.
    */
    static bool setSndBuf(int fd, size_t size);

    //! Set SO_RCVBUF socket option.
    static bool setRcvBuf(int fd, size_t size);

    
    static bool getTcpInfo(int fd, struct tcp_info*) ;
    static bool getTcpInfoString(int fd, char* buf, int len) ;
    
    static bool setSendTimeOut(int fd, Timespan &span);
    static bool setRecvTimeOut(int fd, Timespan &span);


};

}
}
#endif